<?php

/**
 * Redis 扩展，安装见：https://pecl.php.net/package/redis
 */

class Memory_Redis {

	private $object = null;

	public function __construct() {
		$conf = Sdk\lib\Config::GetApp('redis');
		if (!$conf) {
			$conf = Sdk\lib\Config::GetRoot('redis');
		}
		if (!$conf) {
			$conf = array(
				'server' => "127.0.0.1",
				'port' => 6379,
			);
		}
		if ($conf && $this->env()) {
			try {
				$this->object = new Redis();
				if (!empty($conf['pconnect'])) {
					$connect = @$this->object->pconnect($conf['server'], $conf['port']);
				} else {
					$connect = @$this->object->connect($conf['server'], $conf['port']);
				}
			} catch (Exception $e) {
				return;
			}
			if ($connect) {
				if (!empty($conf['requirepass'])) {
					$this->object->auth($conf['requirepass']);
				}
				@$this->object->setOption(Redis::OPT_SERIALIZER, $conf['serializer']);
			}
		}
	}

	public function env() {
		return extension_loaded('redis');
	}

	public function get($key) {
		if (is_array($key)) {
			return $this->getMulti($key);
		}
		$return = $this->object->get($key);
		$this->_unserialize($return);
		return $return;
	}

	public function getMulti($keys) {
		$result = $this->object->getMultiple($keys);
		$newresult = array();
		$index = 0;
		foreach ($keys as $key) {
			if ($result[$index] !== false) {
				$this->_unserialize($result[$index]);
				$newresult[$key] = $result[$index];
			}
			$index++;
		}
		unset($result);
		return $newresult;
	}

	public function select($db = 0) {
		return $this->object->select($db);
	}

	public function set($key, $value, $ttl = 0) {
		$this->_serialize($value);
		if ($ttl) {
			return $this->object->setex($key, $ttl, $value);
		} else {
			return $this->object->set($key, $value);
		}
	}

	public function add($key, $value, $ttl = 0) {
		$this->_serialize($value);
		return $this->object->set($key, $value, array('nx', 'ex' => $ttl));
	}

	public function rm($key) {
		return $this->object->delete($key);
	}

	public function setMulti($arr, $ttl = 0) {
		if (!is_array($arr)) {
			return FALSE;
		}
		foreach ($arr as $key => $v) {
			$this->set($key, $v, $ttl);
		}
		return TRUE;
	}

	public function inc($key, $step = 1) {
		return $this->object->incr($key, $step);
	}

	public function dec($key, $step = 1) {
		return $this->object->decr($key, $step);
	}

	public function getSet($key, $value) {
		$this->_serialize($value);
		return $this->object->getSet($key, $value);
	}

	public function sADD($key, $value) {
		return $this->object->sADD($key, $value);
	}

	public function sRemove($key, $value) {
		return $this->object->sRemove($key, $value);
	}

	public function sMembers($key) {
		return $this->object->sMembers($key);
	}

	public function sIsMember($key, $member) {
		return $this->object->sismember($key, $member);
	}

	public function keys($key) {
		return $this->object->keys($key);
	}

	public function expire($key, $second) {
		return $this->object->expire($key, $second);
	}

	public function sCard($key) {
		return $this->object->sCard($key);
	}

	public function hSet($key, $field, $value) {
		return $this->object->hSet($key, $field, $value);
	}

	public function hDel($key, $field) {
		return $this->object->hDel($key, $field);
	}

	public function hLen($key) {
		return $this->object->hLen($key);
	}

	public function hVals($key) {
		return $this->object->hVals($key);
	}

	public function hIncrBy($key, $field, $incr) {
		return $this->object->hIncrBy($key, $field, $incr);
	}

	public function hGetAll($key) {
		return $this->object->hGetAll($key);
	}

	public function sort($key, $opt) {
		return $this->object->sort($key, $opt);
	}

	public function exists($key) {
		return $this->object->exists($key);
	}

	public function clear() {
		return $this->object->flushAll();
	}

	private function _serialize(&$value) {
		if (is_array($value)) {
			$value = @serialize($value);
		}
	}

	private function _unserialize(&$value) {
		if (substr($value, -1) == '}') {
			$v = @unserialize($value);
			if (is_array($v)) {
				$value = $v;
			}
		}
	}

}